#pragma once
#include "line.h"
#include "AABB.h"

namespace shermit {
	template<typename Float_t>
	inline GENERAL bool intersect(const Line<nv::vec2<Float_t>>& line, const AABB2<Float_t> &box) {
		if (abs(line.d.x) < 1e-6) {
			// line is parallel to y-axis
			return box.ptMin.x < line.o.x && line.o.x < box.ptMax.x;
		}
		Float_t k = line.d.y / line.d.x;
		Float_t b = -line.d.y * line.o.x / line.d.x + line.o.y;
		Float_t y0 = k * box.ptMin.x + b;
		Float_t y1 = k * box.ptMax.x + b;
		if (y0 < box.ptMin.y && y1 < box.ptMin.y) return false;
		if (y0 > box.ptMax.y && y1 > box.ptMax.y) return false;
		return true;
	}

	template<typename Float_t>
	inline GENERAL bool intersect(const Line<nv::vec2<Float_t>>& line, const AABB2_SOA<Float_t>& box, size_t i) {
		if (abs(line.d.x) < 1e-6) {
			// line is parallel to y-axis
			return box.minx[i] < line.o.x && line.o.x < box.maxx[i];
		}
		Float_t k = line.d.y / line.d.x;
		Float_t b = -line.d.y * line.o.x / line.d.x + line.o.y;
		Float_t y0 = k * box.minx[i] + b;
		Float_t y1 = k * box.maxx[i] + b;
		if (y0 < box.miny[i] && y1 < box.miny[i]) return false;
		if (y0 > box.maxy[i] && y1 > box.maxy[i]) return false;
		return true;
	}

	template<typename Float_t>
	inline GENERAL bool intersect(const LineSOA<nv::vec2<Float_t>>& lines, size_t i, const AABB2<Float_t>& box) {
		if (abs(lines.d[i].x) < 1e-6) {
			// line is parallel to y-axis
			return box.ptMin.x < lines.o[i].x && lines.o[i].x < box.ptMax.x;
		}
		Float_t k = lines.d[i].y / lines.d[i].x;
		Float_t b = -lines.d[i].y * lines.o[i].x / lines.d[i].x + lines.o[i].y;
		Float_t y0 = k * box.ptMin.x + b;
		Float_t y1 = k * box.ptMax.x + b;
		if (y0 < box.ptMin.y && y1 < box.ptMin.y) return false;
		if (y0 > box.ptMax.y && y1 > box.ptMax.y) return false;
		return true;
	}

	template<typename Float_t>
	inline GENERAL bool intersect(const LineSOA<nv::vec2<Float_t>>& lines, size_t i, const AABB2_SOA<Float_t>& box, size_t j) {
		if (abs(lines.d[i].x) < 1e-6) {
			// line is parallel to y-axis
			Float_t x = lines.o[i].x;
			return box.minx[j] < x && x < box.maxx[j];
		}
		Float_t k = lines.d[i].y / lines.d[i].x;
		Float_t b = -lines.d[i].y * lines.o[i].x / lines.d[i].x + lines.o[i].y;
		Float_t y0 = k * box.minx[j] + b;
		Float_t y1 = k * box.maxx[j] + b;
		if (y0 + 1e-6 <= box.miny[j] && y1 + 1e-6 <= box.miny[j]) return false;
		if (y0 > box.maxy[j] && y1 > box.maxy[j]) return false;
		return true;
	}
}